package com.yxh.lib_base.ext.viewbinding

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.LifecycleOwner
import androidx.viewbinding.ViewBinding
import com.yxh.lib_base.ext.viewbinding.ext.addObserverDestroyed
import com.yxh.lib_base.ext.viewbinding.ext.inflateMethod
import com.yxh.lib_base.ext.viewbinding.ext.inflateMethodParent
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty

/**
 * 作者 : yuan_xh
 * 时间 : 2022/8/8 9:29
 * 说明 : View中使用 默认
 */


/**
 *  View 中使用
 * 使用：val mBinding by viewBinding<xxxBinding>()
 * 与 [View.viewBinding] 的区别是，
 * */
inline fun <reified T : ViewBinding> View.binding() =
    ViewViewBindingDelegate(T::class.java, this, true)

/**
 *  View 中使用
 * 使用：val mBinding by viewBinding<xxxBinding>()
 *
 * */
inline fun <reified T : ViewBinding> View.viewBinding(parentGroup: ViewGroup? = null) =
    ViewViewBindingDelegate(T::class.java, this, false,parentGroup)

class ViewViewBindingDelegate<T : ViewBinding>(
    classes: Class<T>,
    val act: View,
    val bind: Boolean = true,
    var parentGroup: ViewGroup? = null
) : ReadOnlyProperty<View, T> {
    init {
        when {
            act is LifecycleOwner -> act.lifecycle.addObserverDestroyed { destroyed() }
            act.context is LifecycleOwner -> (act.context as LifecycleOwner).lifecycle.addObserverDestroyed { destroyed() }
        }
    }

    private val layoutInflaterParent = classes.inflateMethodParent()
    private val layoutInflater = classes.inflateMethod()
    private var viewBinding: T? = null

    override fun getValue(parent: View, property: KProperty<*>): T {
        return viewBinding?.run { this } ?: let {
            val bind = when {
                bind -> layoutInflaterParent.invoke(
                    null, LayoutInflater.from(parent.context), parent, true
                ) as T
                parentGroup != null -> layoutInflaterParent.invoke(
                    null, LayoutInflater.from(parent.context), parent, false
                ) as T
                else -> layoutInflater.invoke(null, LayoutInflater.from(parent.context)) as T
            }
            if (bind is ViewDataBinding) {
                if (act is LifecycleOwner) {
                    bind.lifecycleOwner = act
                } else if (act.context is LifecycleOwner) {
                    bind.lifecycleOwner = act.context as LifecycleOwner
                }
            }
            bind.apply { viewBinding = this }
        }
    }

    private fun destroyed() {
        viewBinding = null
    }
}
